using System;
using System.Collections.Generic;
using UnityEngine;
using GamePlay.Framework.Events;
using GamePlay.Features.Shared;

namespace GamePlay.Features.UI
{
    /// <summary>
    /// UI管理器，负责管理UI面板的显示和隐藏
    /// </summary>
    public class UIManager : MonoBehaviour
    {
        #region 单例实现

        private static UIManager _instance;

        public static UIManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject obj = new GameObject("UIManager");
                    _instance = obj.AddComponent<UIManager>();
                    DontDestroyOnLoad(obj);
                }
                return _instance;
            }
        }

        private void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(gameObject);
                return;
            }

            _instance = this;
            DontDestroyOnLoad(gameObject);

            // 初始化UI字典
            _uiPanels = new Dictionary<string, UIPanel>();
            _activePanels = new List<UIPanel>();

            // 注册事件
            RegisterEvents();
        }

        private void OnDestroy()
        {
            // 取消注册事件
            UnregisterEvents();
        }

        #endregion

        #region 字段和属性

        [SerializeField] private Canvas _mainCanvas;
        [SerializeField] private Transform _panelContainer;
        [SerializeField] private bool _debugMode = false;

        // UI面板字典
        private Dictionary<string, UIPanel> _uiPanels;

        // 当前活动的面板
        private List<UIPanel> _activePanels;

        // UI预制体路径
        private const string UI_PREFAB_PATH = "UI/Panels/";

        #endregion

        #region Unity生命周期

        private void Start()
        {
            // 确保有主画布
            if (_mainCanvas == null)
            {
                _mainCanvas = FindObjectOfType<Canvas>();
                if (_mainCanvas == null)
                {
                    GameObject canvasObj = new GameObject("MainCanvas");
                    _mainCanvas = canvasObj.AddComponent<Canvas>();
                    _mainCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
                    canvasObj.AddComponent<UnityEngine.UI.CanvasScaler>();
                    canvasObj.AddComponent<UnityEngine.UI.GraphicRaycaster>();
                    DontDestroyOnLoad(canvasObj);
                }
            }

            // 确保有面板容器
            if (_panelContainer == null)
            {
                _panelContainer = _mainCanvas.transform;
            }
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 显示UI面板
        /// </summary>
        /// <param name="panelName">面板名称</param>
        /// <param name="data">传递给面板的数据</param>
        /// <returns>成功显示返回true，否则返回false</returns>
        public bool ShowPanel(string panelName, object data = null)
        {
            if (string.IsNullOrEmpty(panelName))
            {
                LogError("面板名称不能为空");
                return false;
            }

            // 检查面板是否已存在
            if (_uiPanels.TryGetValue(panelName, out UIPanel panel))
            {
                // 如果面板已经激活，可以考虑刷新数据
                if (panel.gameObject.activeSelf)
                {
                    panel.UpdateData(data);
                    Log($"面板已刷新: {panelName}");
                    return true;
                }

                // 激活面板
                panel.gameObject.SetActive(true);
                panel.Show(data);

                // 更新活动面板列表
                if (!_activePanels.Contains(panel))
                {
                    _activePanels.Add(panel);
                }

                Log($"显示面板: {panelName}");

                // 触发UI显示事件
                EmitEvent(new UIShowArgs { UIName = panelName, Data = data });

                return true;
            }

            // 尝试加载面板预制体
            return LoadAndShowPanel(panelName, data);
        }

        /// <summary>
        /// 隐藏UI面板
        /// </summary>
        /// <param name="panelName">面板名称</param>
        /// <returns>成功隐藏返回true，否则返回false</returns>
        public bool HidePanel(string panelName)
        {
            if (string.IsNullOrEmpty(panelName))
            {
                LogError("面板名称不能为空");
                return false;
            }

            // 检查面板是否存在
            if (_uiPanels.TryGetValue(panelName, out UIPanel panel))
            {
                // 如果面板已经隐藏，直接返回
                if (!panel.gameObject.activeSelf)
                {
                    return true;
                }

                // 隐藏面板
                panel.Hide();
                panel.gameObject.SetActive(false);

                // 更新活动面板列表
                if (_activePanels.Contains(panel))
                {
                    _activePanels.Remove(panel);
                }

                Log($"隐藏面板: {panelName}");

                // 触发UI隐藏事件
                EmitEvent(new UIHideArgs { UIName = panelName });

                return true;
            }

            LogWarning($"未找到要隐藏的面板: {panelName}");
            return false;
        }

        /// <summary>
        /// 隐藏所有面板
        /// </summary>
        public void HideAllPanels()
        {
            foreach (var panel in _activePanels.ToArray())
            {
                panel.Hide();
                panel.gameObject.SetActive(false);
            }

            _activePanels.Clear();

            Log("已隐藏所有面板");
        }

        /// <summary>
        /// 预加载UI面板
        /// </summary>
        /// <param name="panelName">面板名称</param>
        /// <returns>加载成功返回true，否则返回false</returns>
        public bool PreloadPanel(string panelName)
        {
            if (string.IsNullOrEmpty(panelName))
            {
                LogError("面板名称不能为空");
                return false;
            }

            // 检查面板是否已存在
            if (_uiPanels.ContainsKey(panelName))
            {
                Log($"面板已加载: {panelName}");
                return true;
            }

            // 加载UI预制体
            string prefabPath = UI_PREFAB_PATH + panelName;
            GameObject prefab = Resources.Load<GameObject>(prefabPath);

            if (prefab == null)
            {
                LogError($"未找到UI预制体: {prefabPath}");
                return false;
            }

            // 实例化UI
            GameObject uiObject = Instantiate(prefab, _panelContainer);
            uiObject.name = panelName;

            // 获取UIPanel组件
            UIPanel panel = uiObject.GetComponent<UIPanel>();
            if (panel == null)
            {
                LogError($"UI预制体不包含UIPanel组件: {panelName}");
                Destroy(uiObject);
                return false;
            }

            // 添加到字典
            _uiPanels.Add(panelName, panel);

            // 初始化后隐藏
            panel.Initialize();
            uiObject.SetActive(false);

            Log($"预加载面板: {panelName}");
            return true;
        }

        /// <summary>
        /// 设置面板的排序顺序
        /// </summary>
        /// <param name="panelName">面板名称</param>
        /// <param name="order">排序顺序（较大的值显示在前面）</param>
        /// <returns>设置成功返回true，否则返回false</returns>
        public bool SetPanelOrder(string panelName, int order)
        {
            if (_uiPanels.TryGetValue(panelName, out UIPanel panel))
            {
                panel.SetSortingOrder(order);
                return true;
            }

            LogWarning($"未找到要设置排序的面板: {panelName}");
            return false;
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 加载并显示面板
        /// </summary>
        private bool LoadAndShowPanel(string panelName, object data)
        {
            // 加载UI预制体
            string prefabPath = UI_PREFAB_PATH + panelName;
            GameObject prefab = Resources.Load<GameObject>(prefabPath);

            if (prefab == null)
            {
                LogError($"未找到UI预制体: {prefabPath}");
                return false;
            }

            // 实例化UI
            GameObject uiObject = Instantiate(prefab, _panelContainer);
            uiObject.name = panelName;

            // 获取UIPanel组件
            UIPanel panel = uiObject.GetComponent<UIPanel>();
            if (panel == null)
            {
                LogError($"UI预制体不包含UIPanel组件: {panelName}");
                Destroy(uiObject);
                return false;
            }

            // 添加到字典
            _uiPanels.Add(panelName, panel);

            // 初始化并显示
            panel.Initialize();
            panel.Show(data);

            // 更新活动面板列表
            _activePanels.Add(panel);

            Log($"加载并显示面板: {panelName}");

            // 触发UI显示事件
            EmitEvent(new UIShowArgs { UIName = panelName, Data = data });

            return true;
        }

        /// <summary>
        /// 注册事件
        /// </summary>
        private void RegisterEvents()
        {
            // 这里注册需要监听的事件
        }

        /// <summary>
        /// 取消注册事件
        /// </summary>
        private void UnregisterEvents()
        {
            // 取消注册已监听的事件
        }

        /// <summary>
        /// 发送事件
        /// </summary>
        private void EmitEvent<T>(T eventArgs) where T : EventArgs
        {
            EventManager.Instance.RaiseEvent(this, eventArgs);
        }

        /// <summary>
        /// 打印调试日志
        /// </summary>
        private void Log(string message)
        {
            if (_debugMode)
            {
                Debug.Log($"[UIManager] {message}");
            }
        }

        /// <summary>
        /// 打印警告日志
        /// </summary>
        private void LogWarning(string message)
        {
            Debug.LogWarning($"[UIManager] {message}");
        }

        /// <summary>
        /// 打印错误日志
        /// </summary>
        private void LogError(string message)
        {
            Debug.LogError($"[UIManager] {message}");
        }

        #endregion
    }

    /// <summary>
    /// UI面板基类，所有UI面板都应继承此类
    /// </summary>
    public abstract class UIPanel : MonoBehaviour
    {
        [SerializeField] protected Canvas _canvas;
        [SerializeField] protected bool _useAnimation = true;

        /// <summary>
        /// 初始化面板
        /// </summary>
        public virtual void Initialize()
        {
            if (_canvas == null)
            {
                _canvas = GetComponent<Canvas>();
                if (_canvas == null)
                {
                    _canvas = gameObject.AddComponent<Canvas>();
                }
            }
        }

        /// <summary>
        /// 显示面板
        /// </summary>
        /// <param name="data">传递给面板的数据</param>
        public virtual void Show(object data = null)
        {
            gameObject.SetActive(true);

            if (_useAnimation)
            {
                PlayShowAnimation();
            }

            OnShow(data);
        }

        /// <summary>
        /// 隐藏面板
        /// </summary>
        public virtual void Hide()
        {
            if (_useAnimation)
            {
                PlayHideAnimation();
                // 注意：实际隐藏应该在动画完成后
            }
            else
            {
                OnHide();
                gameObject.SetActive(false);
            }
        }

        /// <summary>
        /// 更新面板数据
        /// </summary>
        /// <param name="data">新数据</param>
        public virtual void UpdateData(object data)
        {
            // 由子类实现
        }

        /// <summary>
        /// 设置面板排序顺序
        /// </summary>
        /// <param name="order">排序顺序</param>
        public virtual void SetSortingOrder(int order)
        {
            if (_canvas != null)
            {
                _canvas.sortingOrder = order;
            }
        }

        /// <summary>
        /// 显示时调用
        /// </summary>
        /// <param name="data">传递的数据</param>
        protected virtual void OnShow(object data)
        {
            // 由子类实现
        }

        /// <summary>
        /// 隐藏时调用
        /// </summary>
        protected virtual void OnHide()
        {
            // 由子类实现
        }

        /// <summary>
        /// 播放显示动画
        /// </summary>
        protected virtual void PlayShowAnimation()
        {
            // 由子类实现
        }

        /// <summary>
        /// 播放隐藏动画
        /// </summary>
        protected virtual void PlayHideAnimation()
        {
            // 由子类实现，动画完成后应调用OnHide并禁用游戏对象
        }
    }
}